package org.larkdoc.util;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Java Bean 转换工具类：Dozer
 * 工具比较强大，目前只用了部分功能，基于xml配置的加载还未完成DEMO<br/>
 * 更多强大功能请参阅官网：https://github.com/DozerMapper <br/>
 * DozerBeanMapper 避免过多创建因此创建此工具类。<br/>
 * 
 * @author tmmk
 * @version [v0.0.1, 2016年7月12日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class DozerUtil {
    
    private static Logger LOG   = LoggerFactory.getLogger(DozerUtil.class);
    
    private static Mapper dozer = new DozerBeanMapper();
    
    /**
     * 对象转换
     * 
     * @param source 源对象
     * @param target 目标对象
     * 
     * @return void [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     * @author tmmk
     * @version [v0.0.1, 2016年7月13日]
     */
    public static void conversion(Object source, Object target) {
        dozer.map(source, target);
    }
    
    /**
     * Java Bean 对象转换
     * 
     * @param source 源对象
     * @param targetClass 目标对象的class
     * @return [参数说明]
     * 
     * @return T 返回所传的对象类型
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     * @author tmmk
     * @version [v0.0.1, 2016年7月13日]
     */
    public static <T> T conversion(Object source, Class<T> targetClass) {
        return null == source ? null : dozer.map(source, targetClass);
    }
    
    /**
     * 转换集合
     * 
     * @param source 源数据
     * @param targetClass 目标List泛型
     * @return [参数说明]
     * 
     * @return List<T> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     * @author tmmk
     * @version [v0.0.1, 2016年7月12日]
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static <T> Collection<T> conversionCollection(Collection<?> source, Class<T> targetClass) {
        Collection<T> result = null;
        if (null != source && !source.isEmpty()) {
            Class<? extends Collection> classType = source.getClass();
            try {
                result = classType.newInstance();
            } catch (InstantiationException e) {
                LOG.error("conversionList InstantiationException : ", e);
            } catch (IllegalAccessException e) {
                LOG.error("conversionList IllegalAccessException : ", e);
            }
            result = result == null ? new ArrayList<T>() : result;
            for (Object obj : source) {
                result.add(conversion(obj, targetClass));
            }
        }
        return result;
    }
    
    /**
     * 转换List
     * 
     * @param source 源数据
     * @param targetClass 目标List泛型
     * @return [参数说明]
     * 
     * @return List<T> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     * @author tmmk
     * @version [v0.0.1, 2016年7月12日]
     */
    public static <T> List<T> conversionList(List<?> source, Class<T> targetClass) {
        List<T> result = null;
        if (null != source && !source.isEmpty()) {
            result = new ArrayList<T>(source.size());
            for (Object obj : source) {
                result.add(conversion(obj, targetClass));
            }
        }
        return result;
    }
    
    /**
     * bean转自然排序的TreeMap<br/>
     * @param source 数据源对象
     * @param humpToUnderLine 是否开启驼峰转下划线: true 转；false:不转
     * @param ignoreClass 忽略class属性：true:忽略； false：不忽略
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException [参数说明]
     * 
     * @return Map<Object,Object> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static Map<String, String> toMapNaturalOrder(Object source, boolean humpToUnderLine,
                                                        boolean ignoreClass) throws IllegalAccessException,
                                                                             InvocationTargetException,
                                                                             NoSuchMethodException {
        Map<String, String> result = null;
        if (null != source) {
            Map<?, ?> map = BeanUtils.describe(source);
            if (null != map && !map.isEmpty()) {
                result = new TreeMap<String, String>();
                for (Map.Entry<?, ?> entry : map.entrySet()) {
                    if (null == entry) {
                        continue;
                    }
                    if (ignoreClass && "class".equals(entry.getKey())) {
                        continue;
                    }
                    result.put(humpToUnderLine ? HumpConverter.humpToLine(entry.getKey().toString())
                        : entry.getKey().toString(), null != entry.getValue() ? entry.getValue().toString() : null);
                }
            }
        }
        return result;
    }
    
    /**
     * bean转自然排序的TreeMap(忽略class属性)
     * 
     * @param source 数据源对象
     * @return TreeMap
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException [参数说明]
     * 
     * @return Map<String,Object> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static Map<String, String> toMapNaturalOrder(Object source) throws IllegalAccessException,
                                                                       InvocationTargetException,
                                                                       NoSuchMethodException {
        return toMapNaturalOrder(source, false, true);
    }
    
    /**
     * 对象转自然排序TreeMap<br/>
     * 
     * @param source 源数据对象
     * @param humpToUnderLine 驼峰转下划线: true 转；false:不转
     * @param ignoreClass 忽略class属性： true 忽略； false：不忽略
     * @param matchProperty 匹配的属性列表，可为空
     * @param matchType 属性匹配方式：true:matchProperty值加入TreeMap; false: matchProperty值不加入TreeMap
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException [参数说明]
     * 
     * @return Map<String,Object> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static Map<String, String>
           toMapNaturalOrder(Object source, boolean humpToUnderLine, boolean ignoreClass, String[] matchProperty,
                             boolean matchType) throws IllegalAccessException, InvocationTargetException,
                                                NoSuchMethodException {
        Map<String, String> result = null;
        if (null != source) {
            if (null != matchProperty && matchProperty.length > 0) {
                Map<?, ?> map = BeanUtils.describe(source);
                boolean match = false;
                if (null != map && !map.isEmpty()) {
                    result = new TreeMap<String, String>();
                    for (Map.Entry<?, ?> entry : map.entrySet()) {
                        if (null == entry) {
                            continue;
                        }
                        if (ignoreClass && "class".equals(entry.getKey())) {
                            continue;
                        }
                        if (matchType) {
                            // 正向匹配
                            for (String property : matchProperty) {
                                if (StringUtils.isBlank(property)) {
                                    continue;
                                }
                                if (property.equals(entry.getKey())) {
                                    match = true;
                                    break;
                                }
                            }
                        } else {
                            // 反向匹配，排除屬性
                            match = true;
                            for (String property : matchProperty) {
                                if (StringUtils.isBlank(property)) {
                                    continue;
                                }
                                if (property.equals(entry.getKey())) {
                                    match = false;
                                    break;
                                }
                            }
                        }
                        if (match) {
                            result.put(
                                humpToUnderLine ? HumpConverter.humpToLine(entry.getKey().toString())
                                    : entry.getKey().toString(),
                                null != entry.getValue() ? entry.getValue().toString() : null);
                            match = false;
                        }
                    }
                }
            } else {
                result = toMapNaturalOrder(source, humpToUnderLine, ignoreClass);
            }
        }
        return result;
    }
    
    /**
     * 对象转自然排序字符串：[属性名][middleSplit][属性值][footSplit]
     * @param source 源数据对象
     * @param humpToUnderLine 驼峰转下划线: true 转；false:不转
     * @param ignoreClass 忽略class属性： true 忽略； false：不忽略
     * @param middleSplit 属性拼接中间字符串
     * @param footSplit 属性拼接结尾字符串
     * @param matchProperty 匹配的属性列表，可为空
     * @param matchType 属性匹配方式：true:matchProperty值加入TreeMap; false: matchProperty值不加入TreeMap
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String objToNaturalString(Object source, boolean humpToUnderLine, boolean ignoreClass,
                                            String middleSplit, String footSplit, String[] matchProperty,
                                            boolean matchType) throws IllegalAccessException, InvocationTargetException,
                                                               NoSuchMethodException {
        return mapToString(toMapNaturalOrder(source, humpToUnderLine, ignoreClass, matchProperty, matchType),
            middleSplit, footSplit);
    }
    
    /**
     * 对象转自然排序字符串：属性middleSplit属性值footSplit
     * 
     * @param source 数据源
     * @param humpToUnderLine 驼峰转下划线: true 转；false:不转
     * @param ignoreClass class属性： true 忽略； false：不忽略
     * @param middleSplit 属性拼接中间字符串
     * @param footSplit 属性拼接结尾字符串
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String objToNaturalString(Object source, boolean humpToUnderLine, boolean ignoreClass,
                                            String middleSplit, String footSplit) throws IllegalAccessException,
                                                                                  InvocationTargetException,
                                                                                  NoSuchMethodException {
        return objToNaturalString(source, humpToUnderLine, ignoreClass, middleSplit, footSplit, null, true);
    }
    
    /**
     * 对象转自然排序字符串：属性middleSplit属性值footSplit<br/>
     * 忽略class属性
     * @param source 数据源
     * @param middleSplit 属性拼接中间字符串
     * @param footSplit 属性拼接结尾字符串
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String objToNaturalString(Object source, String middleSplit,
                                            String footSplit) throws IllegalAccessException, InvocationTargetException,
                                                              NoSuchMethodException {
        return objToNaturalString(source, false, true, middleSplit, footSplit, null, true);
    }
    
    /**
     * map对象转字符串:示例：[key][middleSplit][key][footSplit][key][middleSplit][key]<br/>
     * []:仅为区分各值的标识，实际拼接无此符号
     * 
     * @param map
     * @param middleSplit 属性拼接中间字符串
     * @param footSplit 属性拼接结尾字符串
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String mapToString(Map<String, String> map, String middleSplit, String footSplit) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> mapping : map.entrySet()) {
            sb.append(mapping.getKey());
            sb.append(middleSplit);
            sb.append(mapping.getValue());
            sb.append(footSplit);
        }
        String str = sb.toString();
        return StringUtils.isNotBlank(footSplit) ? str.substring(0, str.lastIndexOf(footSplit)) : str;
    }
    
    //    public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    //        AuthResult ar = new AuthResult();
    //        ar.setCode(1);
    //        ar.setMessage("mgs");
    //        ar.setResult(true);
    //        System.out.println(objToNaturalString(ar, false, false, "=", "", null, false));
    //        System.out.println(objToNaturalString(ar, true, true, "=", "&"));
    //        System.out.println(objToNaturalString(ar, "=", ","));
    //        System.out.println(objToNaturalString(ar, false, false, "=", ",", new String[]{"code"}, false));
    //        System.out.println(objToNaturalString(ar, false, false, "=", ",", new String[]{"code"}, true));
    //    }
}
